package br.com.felix.dbm.controller;

import java.util.Iterator;

import br.com.felix.dbm.DatabaseObjectsFactory;
import br.com.felix.dbm.database.Column;
import br.com.felix.dbm.database.PrimaryKey;
import br.com.felix.dbm.database.Table;
import br.com.felix.dbm.ui.ColumnUi;
import br.com.felix.dbm.ui.ForeignKeyUi;
import br.com.felix.dbm.ui.TableUi;

/**
 * Controller for table objects.
 * */
public class TableController implements Comparable<TableController> {

	private Table table;
	private TableUi tableUi;
	/**
	 * Keeps track of the column controllers.
	 * */
	private ColumnControllerSet lstColumnControllers = new ColumnControllerSet();
	private DataModelController dataModelController;



	public TableController(Table table, TableUi tableUi, DataModelController dataModelController) {
		this.table = table;
		this.tableUi = tableUi;
		this.dataModelController = dataModelController;
		for (Column column : table.getColumns()) {
			if (column.isForeignKey(table)) {
				addForeignKeyColumn(column);
			}
			else {
				addColumn(column);
			}
		}
	}



	public Table getModel() {
		return table;
	}



	/**
	 * @param foreignKey is the primary key of another table. Adds the primary
	 *            key of another table as a foreign key in this table.
	 * */
	public void addForeignKey(PrimaryKey foreignKey) {
		table.addForeignKey(foreignKey);
		Column[] fkColumns = foreignKey.getColumns();
		for (Column fkColumn : fkColumns) {
			addForeignKeyColumn(fkColumn);
		}
	}



	/**
	 * Sets up the specified column as a foreign key column.
	 * */
	private void addForeignKeyColumn(Column fkColumn) {
		ForeignKeyUi fkColumnUi = new ForeignKeyUi();
		ColumnController fkColumnController = ColumnController.getInstance(fkColumn);
		if (fkColumnController == null) {
			fkColumnController = ColumnController.newInstance(fkColumn, new ColumnUi(), this);
		}
		fkColumnController.addViewForTable(tableUi, fkColumnUi);
		fkColumnUi.setColumnController(fkColumnController);
		fkColumnUi.updateView(fkColumn);
		lstColumnControllers.add(fkColumnController);
		tableUi.addColumn(fkColumnController);
	}



	/**
	 * Adds a new, empty column.
	 * */
	public ColumnController addColumn() {
		Column newColumn = new Column();
		return addColumn(newColumn);
	}



	/**
	 * Adds the specified column to the table.
	 * */
	private ColumnController addColumn(Column newColumn) {
		ColumnUi newColumnUi;
		ColumnController columnController = ColumnController.getInstance(newColumn);
		if (columnController == null) {
			newColumnUi = new ColumnUi();
			columnController = ColumnController.newInstance(newColumn, newColumnUi, this);
		}
		else {
			newColumnUi = columnController.getView();
		}

		newColumn.setTablePrefix(DatabaseObjectsFactory.getDatabaseNamingRules().tableColumnPrefix(table.getName()));
		lstColumnControllers.add(columnController);
		newColumnUi.setColumnController(columnController);
		newColumnUi.updateView(newColumn);
		table.addColumn(newColumn);
		tableUi.addColumn(columnController);
		return columnController;
	}



	public TableUi getView() {
		return tableUi;
	}



	public void setName(String text) {
		table.setName(text);
	}



	public ColumnControllerSet getColumnControllers() {
		return lstColumnControllers;
	}



	public void updateView() {
		tableUi.updateView();
	}



	/**
	 * Deletes the column from this table. Both from the view and from the
	 * model.
	 * */
	public void deleteColumn(Column column) {
		Iterator<ColumnController> it = lstColumnControllers.iterator();
		ColumnController cc;
		while (it.hasNext()) {
			cc = it.next();
			if (cc.getModel().equals(column)) {
				table.removeColumn(column);
				tableUi.removeColumn(cc);
				it.remove();
				tableUi.updateView();
			}
		}
	}



	public DataModelController getDataModelController() {
		return dataModelController;
	}



	@Override
	public String toString() {
		return "TC for " + table.getName();
	}



	/**
	 * TODO: implement this correctly.
	 * */
	@Override
	public int compareTo(TableController o) {
		boolean areTheSame = this.table!=null && this.table.equals(o.getModel());
		areTheSame &= (this.tableUi != null &&  this.tableUi == o.getView());
		if(areTheSame)return 0;
		return table.getName().compareTo(o.getModel().getName());
	}
	
	
}
